﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MLForgeSharp.Models.ProbabilisticModels
{
    /// <summary>
    /// 马尔科夫链-蒙特卡洛模型
    /// </summary>
    public class MarkovMonteCarlo
    {
        // 目标分布（示例：标准正态分布）
        private static double TargetDistribution(double x)
        {
            return Math.Exp(-0.5 * x * x); // p(x) ∝ exp(-0.5 * x^2)
        }

        // 提议分布（示例：正态分布，均值为当前点，方差为 1）
        private static double ProposalDistribution(double current, double sigma = 1.0)
        {
            Random rand = new Random();
            return current + sigma * (rand.NextDouble() - 0.5) * 2; // 均匀分布
        }

        // Metropolis-Hastings 算法
        public static double[] MetropolisHastings(int numSamples, double initialValue = 0.0, double proposalSigma = 1.0)
        {
            double[] samples = new double[numSamples];
            double current = initialValue;
            Random rand = new Random();

            for (int i = 0; i < numSamples; i++)
            {
                // 生成候选点
                double candidate = ProposalDistribution(current, proposalSigma);

                // 计算接受概率
                double acceptanceRatio = Math.Min(1, TargetDistribution(candidate) / TargetDistribution(current));

                // 决定是否接受候选点
                if (rand.NextDouble() < acceptanceRatio)
                {
                    current = candidate;
                }

                // 保存当前点
                samples[i] = current;
            }

            return samples;
        }
    }

    // 示例程序
    public class MarkovMonteCarloExample
    {
        public MarkovMonteCarloExample()
        {
            // 设置参数
            int numSamples = 10000; // 采样数量
            double initialValue = 0.0; // 初始值
            double proposalSigma = 1.0; // 提议分布的方差

            // 运行 Metropolis-Hastings 算法
            double[] samples = MarkovMonteCarlo.MetropolisHastings(numSamples, initialValue, proposalSigma);

            // 打印部分样本
            Console.WriteLine("采样结果（前 10 个样本）：");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(samples[i]);
            }

            // 计算样本均值和方差
            double mean = 0.0;
            double variance = 0.0;
            for (int i = 0; i < numSamples; i++)
            {
                mean += samples[i];
            }
            mean /= numSamples;

            for (int i = 0; i < numSamples; i++)
            {
                variance += Math.Pow(samples[i] - mean, 2);
            }
            variance /= numSamples;

            Console.WriteLine("\n样本均值: " + mean);
            Console.WriteLine("样本方差: " + variance);
        }
    }
}
